package com.enqualcomm.kids.mvp.heartrate;

import android.accounts.NetworkErrorException;

import com.android.volley.socket.ServerAddress;
import com.android.volley.socket.SocketAddressSwitcher;
import com.android.volley.socket.SocketStack;
import com.enqualcomm.kids.component.MyApplication;
import com.enqualcomm.kids.network.socket.request.HeartParams;
import com.enqualcomm.kids.network.socket.request.HeartRateActiveParams;
import com.enqualcomm.kids.network.socket.response.HeartRateActiveResult;
import com.enqualcomm.kids.network.socket.response.HeartRateQueryResult;
import com.google.gson.Gson;

import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.TimeUnit;

import common.utils.GsonFactory;
import common.utils.MyLogger;
import common.utils.NetUtil;
import common.utils.ThreadTransformer;
import rx.Observable;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Action1;

/**
 * Created by Yinzhiqun on 2016/7/19.
 */
public class HeartRateClient {

    private String json;
    private String heart;
    private Socket socket;
    private final Gson gson;

    public HeartRateClient(String userkey, String userid, String terminalid) {
        gson = GsonFactory.newInstance();
        this.json = gson.toJson(new HeartRateActiveParams(userkey,userid,terminalid));
        this.heart = gson.toJson(new HeartParams(userkey, userid));
    }

    public Observable<HeartRateQueryResult.Result> queryHeartRate(){
        if (!NetUtil.checkNet(MyApplication.getInstance())) {
            return Observable.error(new NetworkErrorException("没有可用网络连接"));
        }else {
            return Observable.create(new Observable.OnSubscribe<HeartRateQueryResult.Result>() {
                private volatile long timeout = 10;//默认10秒之后超时

                @Override
                public void call(Subscriber<? super HeartRateQueryResult.Result> subscriber) {
                    if (!initSocket()) {
                        subscriber.onError(new NetworkErrorException("创建socket失败"));
                        return;
                    }

                    //1.发送请求参数
                    sendParams(json);

                    //2.启动心跳线程维持连接
                    Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe(new Action1<Long>() {
                        @Override
                        public void call(Long aLong) {
                            //检查是否超时
                            if (--timeout<0) {
                                closeSocket();//关闭socket，会导致接收线程中断
                                return;
                            }
                            //发送心跳包
                            if (aLong%10==0){
                                sendParams(heart);
                            }
                        }
                    });
                    subscriber.add(subscription);//取消时也需要中断心跳线程

                    //3.接收数据
                    String str = null;
                    while ((str = receiveData())!=null){
                        HeartRateActiveResult result = gson.fromJson(str, HeartRateActiveResult.class);
                        if (result.code==0){
                            switch (result.result.state){
                                case 0:
                                case 1://检测心率成功
                                    closeSocket();
                                    subscriber.onNext(result.result.content);
                                    subscriber.onCompleted();
                                    return;
                                case 2://手表已收到指令，延迟超时时间
                                    timeout+=90;
                                    break;
                                case 3://手表已关机
                                    closeSocket();
                                    subscriber.onNext(null);
                                    subscriber.onCompleted();
                                    return;
                            }
                        }
                    }

                    if (timeout<0){
                        subscriber.onError(new NetworkErrorException("超时"));
                    }else {
                        closeSocket();
                        subscriber.onError(new NetworkErrorException("连接中断"));
                    }
                }
            }).compose(new ThreadTransformer<HeartRateQueryResult.Result>());
        }
    }

    private boolean initSocket(){
        try {
            ServerAddress serverAddress = new SocketAddressSwitcher(MyApplication.getInstance().getFilesDir() + "/server_config").getServerAddress();
            socket = new Socket(serverAddress.ip,serverAddress.port);
            socket.setKeepAlive(true);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    private void closeSocket(){
        if (socket!=null) {
            try {
                if (!socket.isClosed()) {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                socket = null;
            }
        }
    }

    private String receiveData(){
        String result = null;
        if (socket!=null){
            try {
                byte[] receive = SocketStack.receive(socket);
                result =  new String(receive);
            } catch (Exception e) {
                e.printStackTrace();
            }

            MyLogger.jLog().i(result);
        }
        return result;
    }

    private void sendParams(String str){
        MyLogger.jLog().i(str);
        if (socket!=null) {
            try {
                SocketStack.send(socket,str.getBytes("UTF-8"));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

}
